package com.haoniu.common.util;


import java.text.DecimalFormat;
import java.util.*;

/**
 * 自由生成红包 不受雷点和概率控制
 */
public class RedPacketFree {
    /**
     * 1.总金额不超过200*100  单位是分
     * 2.每个红包都要有钱，最低不能低于1分，最大金额不能超过200*100
     */
    private static final int MINMONEY = 1;
    private static final int MAXMONEY = 1000 * 100;

    /**
     * 这里为了避免某一个红包占用大量资金，我们需要设定非最后一个红包的最大金额，
     * 我们把他设置为红包金额平均值的N倍
     */
    private static final double TIMES = 2.1;

    /**
     * 拆分红包
     *
     * @param money 红包金额
     * @param count 个数
     * @return
     */
    public static double[] getNewRedArrayFree(int money, int count, String leiDian, int happendPercent) {
        double[] newRedArray = new double[count];

        List<String> doubleList =  new ArrayList<String>();
        // 检查雷点数是否等于包的数量
        String[] leiDianCountArray = leiDian.split(",");
        if(count == leiDianCountArray.length){
            // 检查当前雷点总数相加是否等于0  只有等于0 后面才可能分出全部中雷的情况
            int leiDianCount = 0;
            for (int i=0;i<leiDianCountArray.length;i++){
                leiDianCount += Integer.parseInt(leiDianCountArray[i]);
            }
            // 如果可以整除10 则有操作空间 真的要生成 就可以生成
            if(leiDianCount%10 != 0){
                happendPercent = -1;
            }
        }

        // 如果中雷了
        if (isHappendAccordingPercent(happendPercent)) {
            System.out.println("经过了概率检查，必须要中雷");
            boolean haveManyLeiSuccess = true;
            // 最大循环次数 10W次
            int maxCount = 100000;
            while (haveManyLeiSuccess && maxCount > 0) {
                haveManyLeiSuccess = false;
                doubleList = splitRedPacketFree(money, count);
                String[] leiDianArray = leiDian.split(",");
                Map checkMap = new HashMap<>();
                for (int i = 0; i < doubleList.size(); i++) {
                    String thisDoubleStr = doubleList.get(i);
                    String lastIndexInt = thisDoubleStr.substring(thisDoubleStr.length() - 1, thisDoubleStr.length());
                    for (int j = 0; j < leiDianArray.length; j++) {
                        if (lastIndexInt.equals(leiDianArray[j])) {
                            checkMap.put(lastIndexInt, "EXSIT");
                        }
                    }
                }
                // 检查这个红包里是不是包括这些雷
                for (int i = 0; i < leiDianArray.length; i++) {
                    // 如果有一个雷不存在 则表明这个没有中雷
                    if (checkMap.get(leiDianArray[i]) == null) {
                        haveManyLeiSuccess = true;
                        break;
                    }
                }
                maxCount --;
            }
            if(haveManyLeiSuccess){
                throw new RuntimeException("发包失败");
            }
        } else {
            System.out.println("经过了概率检查，必须不能中雷");
            boolean haveManyLeiSuccess = true;
            while (haveManyLeiSuccess) {
                haveManyLeiSuccess = true;
                doubleList = splitRedPacketFree(money, count);
                String[] leiDianArray = leiDian.split(",");
                Map checkMap = new HashMap<>();
                for (int i = 0; i < doubleList.size(); i++) {
                    String thisDoubleStr = doubleList.get(i);
                    String lastIndexInt = thisDoubleStr.substring(thisDoubleStr.length() - 1, thisDoubleStr.length());
                    for (int j = 0; j < leiDianArray.length; j++) {
                        if (lastIndexInt.equals(leiDianArray[j])) {
                            checkMap.put(lastIndexInt, "EXSIT");
                        }
                    }
                }
                // 检查这个红包里是不是包括这些雷
                for (int i = 0; i < leiDianArray.length; i++) {
                    // 如果有一个雷不存在 则表明这个没有中雷
                    if (checkMap.get(leiDianArray[i]) == null) {
                        haveManyLeiSuccess = false;
                        break;
                    }
                }
            }
        }
        System.out.println("得到的结果为：doubleList：" + doubleList);
        for (int i = 0; i < doubleList.size(); i++) {
            newRedArray[i] = Double.parseDouble(doubleList.get(i));
        }
        return newRedArray;
    }


    /**
     * 拆分红包
     *
     * @param money 红包金额
     * @param count 个数
     * @return
     */
    public static List<String> splitRedPacketFree(int money, int count) {
        money = money * 100;
        //红包合法性分析
        if (!isRight(money, count)) {
            return null;
        }
        //红包列表
        List<String> list = new ArrayList<>();
        //每个红包的最大的金额为平均金额的TIMES倍
        int max = (int) (money * TIMES / count);
        max = max > MAXMONEY ? MAXMONEY : max;
        //分配红包
        for (int i = 0; i < count; i++) {
            int one = randomRedPacket(money, MINMONEY, max, count - i);
            DecimalFormat df = new DecimalFormat("0.00");
            String thisDoubleStr = df.format((double) one / 100);
            list.add(thisDoubleStr);
            money -= one;
        }
        return list;
    }

    /**
     * 红包合法性校验
     *
     * @param money
     * @param count
     * @return
     */
    private static boolean isRight(int money, int count) {
        double avg = money / count;
        //小于最小金额
        if (avg < MINMONEY) {
            return false;
        } else if (avg > MAXMONEY) {
            return false;
        }
        return true;
    }

    /**
     * 随机分配一个红包
     *
     * @param money
     * @param minS：最小金额
     * @param maxS：最大金额
     * @param count
     * @return
     */
    private static int randomRedPacket(int money, int minS, int maxS, int count) {
        //若只有一个，直接返回红包
        if (count == 1) {
            return money;
        }
        //如果最大金额和最小金额相等，直接返回金额
        if (minS == maxS) {
            return minS;
        }
        int max = maxS > money ? money : maxS;
        //分配红包正确情况，允许红包的最大值
        int maxY = money - (count - 1) * minS;
        //分配红包正确情况，允许红包最小值
        int minY = money - (count - 1) * maxS;
        //随机产生红包的最小值
        int min = minS > minY ? minS : minY;
        //随机产生红包的最大值
        max = max > maxY ? maxY : max;
        //随机产生一个红包
        return (int) Math.rint(Math.random() * (max - min) + min);
    }

    public static boolean isHappendAccordingPercent(int percentage) {
        Random random = new Random();
        int i = random.nextInt(100);
        if (i >= 0 && i < percentage) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        for (int i = 0;i<=100000;i++) {
            double thisaaa = 0;
            double[] ddd = getNewRedArrayFree(2, 6, "4,5,6", 100);
            for (int j = 0; j < ddd.length; j++) {
                thisaaa += ddd[j];
            }
            System.out.println("加一块是多少：" + thisaaa);
        }

    }
}
